package com.example.demo.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.example.demo.model.entity.User;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author KUBUB
 */
public class TokenUtils {

    /**
     * token 密钥
     **/
    private static final String SECRET = "dnCisKqnxg5L3xtV";
    /**
     * token 过期时间：2hour
     **/
    private static final int calendarField = Calendar.HOUR;
    private static final int calendarInterval = 2;

    /**
     * 生成token
     *
     * @param user
     * @return
     */
    public static String getToken(User user) {
        // 获取加上过期时间后的时间
        Date iatDate = new Date();
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(calendarField, calendarInterval);
        Date expiresDate = nowTime.getTime();


        Map<String, Object> map = new HashMap<>(2);
        map.put("alg", "HS256");
        map.put("typ", "JWT");

        String token = JWT.create()
                // 设置 JWT 头部
                .withHeader(map)
                /**
                 * iss: jwt签发者
                 * sub: jwt所面向的用户
                 * aud: 接收jwt的一方
                 * exp: jwt的过期时间，这个时间必须要大于签发时间
                 * nbf: 定义在什么时间之前，该jwt都是不可用的
                 * iat: jwt的签发时间
                 * jti: jwt的唯一身份标识，主要用来作为一次性token，从而回避重放攻击
                 */
                // 设置签发者
                .withClaim("iss", "Service")
                // 设置接收方
                .withClaim("aud", "Client")
                // 将user id 保存到 token 里面
                .withClaim("user_id", user.getId() == null ? null : String.valueOf(user.getId()))
                // 设置当前时间
                .withIssuedAt(iatDate)
                // 设置过期时间
                .withExpiresAt(expiresDate)
                // 设置 token 的密钥
                .sign(Algorithm.HMAC256(SECRET));
        return token;
    }

    /**
     * 验证token
     *
     * @param token
     * @return
     */
    public static boolean verifyToken(String token) {
        try {
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
            jwtVerifier.verify(token);
        } catch (JWTVerificationException e) {
            throw new RuntimeException("401");
        }
        return true;
    }

    /**
     * 解析token中用户的id
     *
     * @param token
     * @return
     */
    public static String getUserID(String token) {
        DecodedJWT jwt = null;
        Claim user_id = null;
        try {
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
            jwt = jwtVerifier.verify(token);
            user_id = jwt.getClaim("user_id");
        } catch (JWTVerificationException e) {
            throw new RuntimeException("401");
        }
        return user_id.asString();
    }


}
